

package org.example.quartz.BIP;

import cn.hutool.core.date.StopWatch;
import cn.hutool.db.Entity;
import cn.hutool.db.Session;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSONObject;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.example.quartz.service.LogService;
import org.example.quartz.service.OrgService;
import org.example.quartz.service.UtilService;
import org.example.quartz.task.QuartzTaskJob;
import org.example.quartz.util.DataSourceUtil;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.JobExecutionContext;
import org.quartz.PersistJobDataAfterExecution;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Slf4j
@Component
// 再Job被执行结束后，将会更新JobDataMap，这样下次Job执行后悔使用新的值而不是初始值
@PersistJobDataAfterExecution
// 同一时间将只有一个Job实例被执行，为了避免并发问题导致数据紊乱，建议这两个注解一起使用
@DisallowConcurrentExecution
public class ItemQuartz_BIPBAK implements QuartzTaskJob {


    Map<String, Object> gsMap = DataSourceUtil.getGS();
    //全局接口配置
    String IP = (String) gsMap.get("IP");
    String PORT = (String) gsMap.get("PORT");
    String ECC = (String) gsMap.get("ECC");
    String Bearer = (String) gsMap.get("Bearer");

    //日志
    LogService loginfo = SpringUtil.getBean(LogService.class);
    //orgService
    OrgService orgService = SpringUtil.getBean(OrgService.class);
    //orgService
    UtilService utilService = SpringUtil.getBean(UtilService.class);


    /**
     * 项目接口
     * 接口地址：GSCloud文档3.7
     * http://ip:port/api/jg/syncbddata/v1.0/bdsyncinterface/syncHsxm
     **/
    @SneakyThrows
    @Override
    public void execute(JobExecutionContext context) {
        Session oracleSession = DataSourceUtil.getLSOracleSession();
        try {
            //传入变量 lastTime 最后抓取时间
            //链接BIP数据库，查询出需要同步的数据，根据TS时间进行判断。
            //TS从中间库表获取到最后一次更新时间，根据此时间进行增量查询推送；
            //中间库日志表记录推送日志，成功、失败、返回信息等（备查）
            //中间库记录最后推送数据的时间，根据时间进行下次查询的条件；
            //String YEAR = utilService.getYEAR();
            // int YEAR = LocalDateTime.now().getYear();
            String methodName = "ItemQuartz";
            JdbcTemplate jdbcTemplate = SpringUtil.getBean(JdbcTemplate.class);
            //查询核算项目-中间配置表，看有多少需要同步的核算项目，让后做循环处理
            String itemClassSQL = "SELECT\n" +
                    "\tid,\n" +
                    "\tnum,\n" +
                    "\tdoccode,\n" +
                    "\tdocname,\n" +
                    "\tgscode,\n" +
                    "\ttablename,\n" +
                    "\ttablekey,\n" +
                    "\tcodekey,\n" +
                    "\tnamekey,\n" +
                    "\tfzpk,\n" +
                    "\tfreekey,\n" +
                    "\tistrue,\n" +
                    "\tts \n" +
                    "FROM\n" +
                    "" + utilService.getGSYY() + ".freemap f \n" +
                    "WHERE\n" +
                    "\tf.istrue = 'NO'";
            List<Map<String, Object>> itemClassMaps = jdbcTemplate.queryForList(itemClassSQL);
            for (Map<String, Object> itemClassObj : itemClassMaps) {

                String itemClass = methodName + "-" + itemClassObj.get("docname");
                String docCode = (String) itemClassObj.get("gscode");
                //1、查询时间
                String ts = utilService.getTs(itemClass, jdbcTemplate);
                //2、根据时间查询数据集 (停用和删除的过滤掉，暂不考虑，线下处理)
                String selectSQL = "SELECT" +
                        " TO_CHAR(SYSDATE,'YYYY') AS YEAR, " +
                        " " + itemClassObj.get("codekey") + " AS CODE," +
                        " " + itemClassObj.get("namekey") + " AS NAME," +
                        " " + itemClassObj.get("tablekey") + " AS ID," +
                        " TS AS TS" +
                        " FROM" +
                        " " + utilService.getOracle() + "." + itemClassObj.get("tablename") + utilService.getHZ() + "" +
                        " WHERE " + itemClassObj.get("codekey") + " IS NOT NULL";
//                        " DR = 0" +
//                        " and " + itemClassObj.get("codekey") + " IS NOT NULL";
                System.out.println(itemClassObj.get("tablename"));
                if (itemClassObj.get("tablename").equals("bd_defdoc")) {
                    selectSQL += " and bd_defdoc.PK_DEFDOCLIST = '" + itemClassObj.get("fzpk") + "'";
                }
                selectSQL += " AND " +
                        " TS >'" + ts + "'" +
                        " ORDER BY TS ASC";
                //查询数据，根据数据结果推送给GS浪潮
                System.out.println(selectSQL);

                List<Entity> query0 = oracleSession.query(selectSQL);
                System.out.println(itemClass + ":" + query0.size());
                if (query0.size() == 0) {
                    System.out.println("暂无新数据推送");
                } else {
                    //获取年份
                    List<Integer> years = utilService.getYEARS();
                    //如果query0有数据，则添加一个wu、无数据到项目档案中；
                    List<List<Entity>> queryList = this.splitLsit(query0, 20);
                    for (List<Entity> query : queryList) {
                        String TS = "";
                        //拼装数据，推送给浪潮
                        String yyids = "";
                        if (query.size() > 0) {
                            //循环年度一年一年进行推送
                            for (int YEAR : years) {
                                System.out.println("推送年份为：" + YEAR);
                                String GsJson = "[";
                                for (Map<String, Object> gSmap : query) {
                                    //根据组织编码，查询出账套信息，如果有多个账套，轮询进行处理
                                    List<Map<String, Object>> yyztCodeMap = orgService.selectCusZtCode(jdbcTemplate);
                                    //账簿轮询
                                    for (int x = 0; x < yyztCodeMap.size(); x++) {
                                        String yyztCode = (String) yyztCodeMap.get(x).get("gsCode");
                                        String orgCode = (String) yyztCodeMap.get(x).get("gsCode");
                                        String CATEGORY = docCode;
                                        GsJson +=
                                                "{\n" +
                                                        "    \"YEAR\":\"" + YEAR + "\",\n" +
                                                        "    \"CODE\":\"" + yyztCode + gSmap.get("ID") + gSmap.get("CODE") + "\",\n" +
                                                        "    \"NAME\":\"" + gSmap.get("ID") + gSmap.get("CODE") + gSmap.get("NAME") + yyztCode + "\",\n" +
                                                        "    \"ORGCODE\":\"" + orgCode + "\",\n" +
                                                        "    \"CATEGORY\":\"" + CATEGORY + "\",\n" +
                                                        "    \"PARENTCODE\":\"\",\n" +
                                                        "    \"FULLNAME\":\"\",\n" +
                                                        "    \"PLAINTEXT1\":\"" + gSmap.get("CODE") + "\",\n" +
                                                        "    \"PLAINTEXT2\":\"" + gSmap.get("NAME") + "\",\n" +
                                                        "    \"SECRETLEVEL\":\"PUBLIC\"\n" +
                                                        "},";

                                    }
                                    yyids += gSmap.get("ID") + ",";
                                    TS = (String) gSmap.get("TS");
                                }
                                //去掉拼接的最后一个字符
                                GsJson = GsJson.substring(0, GsJson.lastIndexOf(','));
                                GsJson += "]";
                                //调用GS接口，推送给GS浪潮，获取返回值;
                                GsJson = GsJson.replace("'", "&#39;")
                                        .replace("‘", "\\‘")
                                        .replace("/", "\\\\/")
                                        .replace("%", "\\u0025")
                                        .replace("_", "\\\\_")
                                        //.replace("\\\\", "\\")  // 反斜杠
                                        .replace("\\n", "\n")   // 换行符
                                        .replace("\\r", "\r")   // 回车符
                                        .replace("\\t", "\t")   // 制表符
                                        .replace("\\\"", "\"")  // 双引号
                                        .replace("\\'", "'");   // 单引号
                                // GsJson.replace("‘", "\\‘").replaceAll("/", "\\/").replaceAll("%", "\\%").replaceAll("_", "\\_").replaceAll("'", "''").replaceAll("\\\\", "\\\\\\\\").replaceAll("%", "\\\\%").replaceAll("_", "\\\\_");
                                //1、推送用户档案
                                StopWatch st = new StopWatch();
                                System.out.println(itemClass + "开始时间：" + LocalDateTime.now());
                                st.start();
                                String gsUrl = IP + ":" + PORT + "/api/jg/syncbddata/v1.0/bdsyncinterface/syncHsxmList";
                                String returnMSG = HttpRequest.post(gsUrl)
                                        .header("Content-Type", "application/json")
                                        .header("Accept-Language", "zh-CHS")
                                        .header("X-ECC-Current-Tenant", ECC)
                                        .header("Authorization", Bearer).timeout(600000)
                                        .body(GsJson).execute().body();
                                st.stop();
                                System.out.println(itemClass + "结束时间：" + LocalDateTime.now());
                                System.out.println(itemClass + "接口耗时：" + st.getTotalTimeMillis() + "ms");
                                System.out.println(itemClass + "返回值：" + returnMSG);
                                if (!returnMSG.isEmpty()) {
                                    String logInsert = "";
                                    returnMSG = returnMSG.replace("'", "\\\\''");

                                    JSONObject returnObj = JSONObject.parseObject(returnMSG);
                                    //成功
                                    if (returnObj.get("code") == null || "".equals(returnObj.get("code"))) {
                                        if (returnObj.get("Code") == null || ("").equals(returnObj.get("Code"))) {
                                            //写入日志表
                                            int loginsert = loginfo.loginfoItem(jdbcTemplate, itemClass, LocalDateTime.now().toString(), "数据返回异常", query0.size(), GsJson, returnMSG, "", yyids, gsUrl, TS);
                                            if (loginsert > 0) {
                                                //System.out.println("日志写入成功！！");
                                            } else {
                                                System.out.println("日志写入失败！！");
                                            }
                                        }
                                    } else if (returnMSG.contains("\"Code\":null,\"")) {
                                        //写入日志表
                                        int loginsert = loginfo.loginfoItem(jdbcTemplate, itemClass, LocalDateTime.now().toString(), "数据返回异常", query0.size(), GsJson, returnMSG, "", yyids, gsUrl, TS);
                                        if (loginsert > 0) {
                                            //System.out.println("日志写入成功！！");
                                        } else {
                                            System.out.println("日志写入失败！！");
                                        }
                                    } else {
                                        if (returnObj.get("code").equals("0")) {
                                            //写入日志表
                                            int loginsert = loginfo.loginfoItem(jdbcTemplate, itemClass, LocalDateTime.now().toString(), "成功", query0.size(), GsJson, returnMSG, "", yyids, gsUrl, TS);
                                            if (loginsert > 0) {
                                                //System.out.println("日志写入成功！！");
                                            } else {
                                                System.out.println("日志写入失败！！");
                                            }
                                            //失败
                                        } else if (returnObj.get("code").equals("1")) {
                                            //写入日志表
                                            int loginsert = loginfo.loginfoItem(jdbcTemplate, itemClass, LocalDateTime.now().toString(), "失败", query0.size(), GsJson, returnMSG, "", yyids, gsUrl, TS);
                                            if (loginsert > 0) {
                                                //System.out.println("日志写入成功！！");
                                            } else {
                                                System.out.println("日志写入失败！！");
                                            }
                                        } else if (returnObj.get("code") == null && ("").equals(returnObj.get("code"))) {
                                            //写入日志表
                                            int loginsert = loginfo.loginfoItem(jdbcTemplate, itemClass, LocalDateTime.now().toString(), "数据返回异常", query0.size(), GsJson, returnMSG, "", yyids, gsUrl, TS);
                                            if (loginsert > 0) {
                                                //System.out.println("日志写入成功！！");
                                            } else {
                                                System.out.println("日志写入失败！！");
                                            }
                                        }
                                    }
                                }

                            }
                        } else {
                            System.out.println("暂无新数据推送");
                        }
                    }

                }

            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            //关闭链接
            DataSourceUtil.closeOracleSession();
            DataSourceUtil.closeMysqlSession();
        }
    }

    public static void main(String[] args) {
        String GsJson =
                "{\n" +
                        //  "    \"YEAR\":\"" + gSmap.get("YEAR") + "\",\n" +
                        "    \"YEAR\":\"" + 2025 + "\",\n" +
                        "    \"CODE\":\"" + "202020222" + "\",\n" +
                        "    \"NAME\":\"" + "11231212_Ceshi123" + "\",\n" +
                        "    \"ORGCODE\":\"" + 10000 + "\",\n" +
                        "    \"CATEGORY\":\"" + 10000000 + "\",\n" +
                        "    \"PARENTCODE\":\"\",\n" +
                        "    \"FULLNAME\":\"\",\n" +
                        "    \"SECRETLEVEL\":\"PUBLIC\"\n" +
                        "aa" + ":" + "" + "," +
                        "},";


        GsJson = GsJson.replace("'", "&#39;")
                .replace("‘", "\\‘")
                .replace("/", "\\/")
                .replace("%", "\\u0025")
                .replace("_", "\\\\_")
                //.replace("\\\\", "\\")  // 反斜杠
                .replace("\\n", "\n")   // 换行符
                .replace("\\r", "\r")   // 回车符
                .replace("\\t", "\t")   // 制表符
                //.replace("\\\"", "\"")  // 双引号
                .replace("\\'", "'");   // 单引号
        System.out.println(GsJson);
    }

    //根据固定长度，拆分成List
    public List<List<Entity>> splitLsit(List<Entity> list, int len) {
        if (list == null || list.size() == 0 || len < 1) {
            return null;
        }
        List<List<Entity>> result = new ArrayList<>();

        int size = list.size();
        int count = (size + len - 1) / len;

        for (int i = 0; i < count; i++) {
            List<Entity> subList = list.subList(i * len, ((i + 1) * len > size ? size : len * (i + 1)));
            result.add(subList);
        }
        return result;
    }


}
